/***************************************************************
 * 系统名称           : 生鲜MIS系统
 * 处理内容           : 继承 BandedGridView，并初始化 BandedGridView，增加相关通用方法或事件
 * @author            : 
 * @Modify            : geping@2016-01-13
 * @description       : 
 * @version           : v1.0
 * @Copyright         : 宁波康铭泰克信息科技有限公司
 * 
 ***************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Comteck.Winforms.Controls.Components;
using Comteck.Winforms.Utils;
using DevExpress.Data.Filtering;
using DevExpress.Utils;
using DevExpress.Utils.Serializing;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Registrator;
using DevExpress.XtraGrid.Views.BandedGrid;
using DevExpress.XtraGrid.Views.BandedGrid.Handler;
using DevExpress.XtraGrid.Views.BandedGrid.ViewInfo;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Base.Handler;
using DevExpress.XtraGrid.Views.Base.ViewInfo;
using DevExpress.XtraGrid.Views.Grid;

namespace Comteck.Winforms.Controls {
  /// <summary>
  /// 自定义的BandedGridView
  /// </summary>
  public class MyBandedGridView : BandedGridView {
    /// <summary>
    /// 当光标在末行最后一个指定字段时继续回车的跳转方式
    /// </summary>
    public enum EnumForwardType {
      [Description("跳转到首行首列")]
      Circle = 0,
      [Description("停止跳转，直接返回")]
      Stop = 1,
      [Description("新增一行，光标定位到新行指定列")]
      NewRow = 2,
    }

    /// <summary>
    /// Default View Name
    /// </summary>
    protected override string ViewName => "MyBandedGridView";

    #region 自定义属性

    //
    // 摘要:                                                        
    //     当 GridView 没有数据时是否显示提示，提示的值由Tag属性设置   geping@2015-10-14
    [DefaultValue(false),]
    [DXCategory("自定义属性")]
    [Description("当 GridView 没有数据时是否显示提示，提示的值由 EmptyForegroundText 属性设置")]
    [XtraSerializableProperty]
    public virtual bool EnableShowEmptyForeground { get; set; }
    //
    // 摘要:
    //     当 GridView 没有数据时的默认提示.   geping@2015-10-14
    [DefaultValue(typeof(string), "")]
    [DXCategory("自定义属性")]
    [Description("当 GridView 没有数据时显示的值，默认显示\"没有查询到你所想要的数据!\"")]
    [XtraSerializableProperty]
    public virtual string EmptyForegroundText { get; set; }
    //
    // 摘要:
    //     GridView 回车时按指定字段跳转到相应的单元格.              geping@2016-11-25
    //     调用方法如：new List<string>() { "SKUCODE", "PRICE", "DESCRIPTION" };   
    [DefaultValue(typeof(List<string>), "")]
    [DXCategory("自定义属性")]
    [Description("指定可以跳转的列（FieldName)，回车时按值先后顺序跳转")]
    [XtraSerializableProperty]
    [TypeConverter(typeof(CollectionConverter))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [Browsable(false)]
    public virtual List<string> ForwardColumnList { get; set; }
    //
    // 摘要:
    //     当光标在末行最后一个指定字段时继续回车的跳转方式.     geping@2016-12-15
    [DefaultValue(typeof(EnumForwardType), "Circle")]
    [DXCategory("自定义属性")]
    [Description("当光标在末行最后一个指定字段时继续回车的跳转方式")]
    [XtraSerializableProperty]
    public virtual EnumForwardType ForwardType { get; set; } = EnumForwardType.Circle;
    //
    // 摘要:
    //     当末行最后一列回车新增行时，指定光标在新行定位的列（FieldName).     geping@2016-12-20
    [DefaultValue(typeof(string), "")]
    [DXCategory("自定义属性")]
    [Description("当末行最后一列回车新增行时，指定光标在新行定位的列（FieldName)，默认为新增行首个可编辑列")]
    [XtraSerializableProperty]
    public virtual string LocatedColumn { get; set; }
    //
    // 摘要:
    //     是否启用基类右键弹出 PopupMenuShowing 事件.     geping@2016-02-20
    [DefaultValue(true)]
    [DXCategory("自定义属性")]
    [Description("是否启用基类鼠标右键 PopupMenuShowing 事件")]
    [XtraSerializableProperty]
    public virtual bool EnablePopupMenuShowing { get; set; } = true;

    #endregion

    public delegate void AddNewLineDelegate();
    /// <summary>
    /// 新增行自定义事件  add by geping@2017-01-09
    /// </summary>
    public AddNewLineDelegate AddNewLineEventHandler;

    /// <summary>
    /// Create a new MyBandedGridView object
    /// </summary>
    public MyBandedGridView()
      : this(null) {
      Initialize();
    }

    /// <summary>
    /// Create a new MyBandedGridView object
    /// </summary>
    /// <param name="grid"></param>
    public MyBandedGridView(DevExpress.XtraGrid.GridControl grid)
      : base(grid) {
      Initialize();
    }

    /// <summary>
    /// 初始化，设置默认值
    /// </summary>
    public void Initialize() {
      this.OptionsFilter.ColumnFilterPopupMode = DevExpress.XtraGrid.Columns.ColumnFilterPopupMode.Classic;

      // 设置为多选
      //this.OptionsSelection.MultiSelect = true;

      // 隐藏提示
      //this.OptionsView.ShowGroupPanel = false;
      // 是否自适应列宽度
      this.OptionsView.ColumnAutoWidth = false;
      // 是否启用偶数行外观                                               
      this.OptionsView.EnableAppearanceEvenRow = true;
      // 是否启用奇数行外观
      this.OptionsView.EnableAppearanceOddRow = true;
      // 是否显示过滤面板
      //this.OptionsView.ShowFilterPanelMode = ShowFilterPanelMode.Never;

      // 禁用单击列弹出右键菜单
      //this.OptionsMenu.EnableColumnMenu = true;

      // 禁止编辑
      //this.OptionsBehavior.Editable = false;
      // 编辑模式
      this.OptionsBehavior.EditorShowMode = EditorShowMode.MouseUp;

      // 打印效果
      this.OptionsPrint.AutoWidth = false;

      // 字段标题居中
      //this.Appearance.HeaderPanel.TextOptions.HAlignment = HorzAlignment.Center;

      // 选中行颜色
      this.Appearance.SelectedRow.BackColor = Color.FromArgb(180, 225, 255);
      this.Appearance.SelectedRow.ForeColor = Color.Black;
      this.Appearance.SelectedRow.Options.UseBackColor = true;
      this.Appearance.SelectedRow.Options.UseForeColor = true;
      // 焦点行颜色
      this.Appearance.FocusedRow.BackColor = Color.FromArgb(180, 225, 255);
      this.Appearance.FocusedRow.ForeColor = Color.Black;
      this.Appearance.FocusedRow.Options.UseBackColor = true;
      this.Appearance.FocusedRow.Options.UseForeColor = true;
      //this.SetAppearanceColor();

      // 是否回车后光标移到下一个单元格
      this.OptionsNavigation.EnterMoveNextColumn = true;

      // 是否允许移动列
      this.OptionsCustomization.AllowColumnMoving = true;

      // 默认选中第一行
      this.FocusedRowHandle = 0;
      // 设置行号宽度
      this.IndicatorWidth = 50;
      this.Focus();
    }

    /// <summary>
    /// 设置单元格是否可编辑
    /// 当 GridView 属性 Editable 设置为true时，指定可以编辑的列（FieldName)，其余列不可以编辑
    /// <para>add by geping@2016-05-23，增加可编辑字段的单元格标题字体色</para>
    /// <paramref name="editableColumnsList"/>
    /// </summary>
    public void SetEditableColumns(List<string> editableColumnsList) {
      if (this.OptionsBehavior.Editable && editableColumnsList != null && editableColumnsList.Count > 0) {
        foreach (GridColumn col in this.Columns) {
          if (editableColumnsList.Exists(x => x == col.FieldName)) {
            // 设置单元格背景色
            //col.AppearanceCell.BackColor = Color.FromArgb(255, 255, 192);           
            // 设置标题字体色
            col.AppearanceHeader.ForeColor = Color.Blue;
            col.OptionsColumn.AllowEdit = true;
          } else {
            // 设置单元格背景色
            //col.AppearanceCell.BackColor = Color.FromArgb(255, 255, 255);
            // 设置标题字体色
            col.AppearanceHeader.ForeColor = Color.Black;
            col.OptionsColumn.AllowEdit = false;
          }
        }
      }
    }

    /// <summary>
    /// 判断是否为表格最后一列可编辑列 add by geping@2016-12-19
    /// </summary>
    /// <param name="view"></param>
    /// <param name="focusedColumn"></param>
    /// <returns></returns>
    private bool IsLastEditableColumn(GridColumn focusedColumn) {
      var index = this.VisibleColumns.IndexOf(focusedColumn);

      for (int i = this.VisibleColumns.Count - 1; i >= 0; i--) {
        GridColumn column = this.VisibleColumns[i];
        // 忽略不可编辑Column 
        if (!column.OptionsColumn.AllowEdit) continue;
        // 当前列如果是最后一列可编辑列，则返回True，否则返回False
        return index == i;
      }
      // 如果都不可编辑，则返回False
      return false;
    }

    /// <summary>
    /// 添加新行  add by geping@2016-12-19
    /// </summary>
    private void AddNewLine() {
      var list = this.GridControl.DataSource;
      // 获取当前实例的 Type
      Type t = this.DataSource.GetType();
      // 动态创建实例
      var obj = Activator.CreateInstance(t.GetGenericArguments()[0]);
      // 调用公用方法 Add
      MethodInfo method = t.GetMethod("Add");
      // 将构建好的实例添加到数据源中
      method.Invoke(list, new object[] { obj });
      // 刷新数据源
      this.RefreshData();
    }

    /// <summary>  
    /// 获取GridView过滤或排序后的数据集  
    /// </summary>  
    /// <typeparam name="T">泛型对象</typeparam>  
    /// <returns></returns>  
    public IEnumerable<T> GetFilteredDataSource<T>() where T : class {
      var list = new List<T>();
      for (int i = 0; i < this.RowCount; i++) {
        if (this.IsGroupRow(i)) continue;

        var entity = this.GetRow(i) as T;
        if (entity == null) continue;

        list.Add(entity);
      }
      return list;
    }

    /// <summary>
    /// 获取选中行的数据集合
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="gv"></param>
    /// <returns></returns>
    public List<T> GetSelectedRowsList<T>() where T : class, new() {
      // 获取选中行的行号
      var rowIds = this.GetSelectedRows();

      return rowIds?.Where(x => x >= 0).Select(x => this.GetRow(x) as T).ToList();
    }

    /// <summary>
    /// 获取选中行的行号及对应行数据集合
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public List<(int rowHandle, T entity)> GetSelectedRowsCollection<T>() where T : class, new() {
      // 获取选中行的行号
      var rowIds = this.GetSelectedRows();

      return rowIds?.Where(x => x >= 0).Select(x => (x, this.GetRow(x) as T)).ToList();
    }

    /// <summary>
    /// 获取GridView的选中行数据集（数据源是 DataTable） add by geping@2019-01-05
    /// 注：未测试过
    /// </summary>
    /// <returns></returns>
    public DataTable GetSelectedDataRows() {
      var dt = (this.DataSource as DataView).Table.Clone();
      var rowIds = this.GetSelectedRows();

      foreach (var id in rowIds) {
        var row = (this.GetRow(id) as DataRowView).Row;
        if (row == null) continue;

        dt.Rows.Add(row.ItemArray);
      }
      return dt;
    }

    /// <summary>
    /// 根据DPI重新计算列宽
    /// </summary>
    private void ReCaculateWidthByDPI() {
      if (!this.OptionsView.ColumnAutoWidth) {
        var sizeF = SysGlobal.DpiSizeF == null ? this.GridControl.ScaleFactor : SysGlobal.DpiSizeF;
        foreach (GridColumn column in this.Columns) {
          column.Width = DevExpress.Skins.RectangleHelper.ScaleHorizontal(column.Width, sizeF.Width);
        }
      }
    }

    /// <summary>
    /// 在初始化后注册一些事件
    /// </summary>
    public override void EndInit() {
      base.EndInit();

      // 注册鼠标右键
      if (this.EnablePopupMenuShowing) {
        this.PopupMenuShowing += DevHelper.MyGridView_PopupMenuShowing;
      }
      this.MouseUp += MyGridView_MouseUp;
      // 注册鼠标右键
      //this.PopupMenuShowing += DevHelper.MyGridView_PopupMenuShowing;
      // 设置行号
      this.CustomDrawRowIndicator += new RowIndicatorCustomDrawEventHandler(MyBandedGridView_CustomDrawRowIndicator);
      // 设置行号宽度
      this.RowCountChanged += new EventHandler(MyBandedGridView_RowCountChanged);
      // 在查询得到0条记录时显示自定义的字符提示/显示
      this.CustomDrawEmptyForeground += new CustomDrawEventHandler(MyBandedGridView_CustomDrawEmptyForeground);
      // 回车跳转单元格（配合 ForwardColumnList 使用）
      this.KeyDown += new KeyEventHandler(MyBandedGridView_KeyDown);

      this.ReCaculateWidthByDPI();
    }

    #region 单击进入编辑状态

    /// <summary>
    /// 单击进入编辑状态
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void MyGridView_MouseUp(object sender, MouseEventArgs e) {
      //// 非左键
      //if (e.Button != MouseButtons.Left)
      //{
      //    return;
      //}

      //GridView view = null;

      //// 传递对象
      //if (sender is BandedGridView)
      //{
      //    view = sender as BandedGridView;
      //}
      //else if (sender is GridView)
      //{
      //    view = sender as GridView;
      //}

      //// 选择多列
      //if (view.GetSelectedCells().Length > 1)
      //{
      //    return;
      //}

      //// 选中的区域
      //GridHitInfo hi = view.CalcHitInfo(e.Location);

      //// 不在单元格中
      //if (hi.InRowCell == false)
      //{
      //    return;
      //}

      //// 不能编辑
      //if (hi.Column.OptionsColumn.AllowEdit == false)
      //{
      //    return;
      //}

      //// 根据不同列分别处理
      //if (hi.Column.RealColumnEdit is RepositoryItemCheckEdit)
      //{
      //    view.FocusedColumn = hi.Column;
      //    view.FocusedRowHandle = hi.RowHandle;

      //    var columnEdit = (RepositoryItemCheckEdit)hi.Column.RealColumnEdit;
      //    object value2 = null;
      //    var value = view.GetRowCellValue(hi.RowHandle, hi.Column);
      //    //var value = view.GetFocusedRowCellValue(view.FocusedColumn);
      //    if (value.To<int>() == columnEdit.ValueChecked.To<int>())
      //    {
      //        value2 = columnEdit.ValueUnchecked;
      //    }
      //    else
      //    {
      //        value2 = columnEdit.ValueChecked;
      //    }

      //    view.SetFocusedRowCellValue(view.FocusedColumn, value2);
      //}
      //else if ((hi.Column.RealColumnEdit as RepositoryItemPopupBase) != null)
      //{
      //    view.FocusedColumn = hi.Column;
      //    view.FocusedRowHandle = hi.RowHandle;
      //    this.GridControl.BeginInvoke(new MethodInvoker(delegate ()
      //    {
      //        if (view.ActiveEditor is PopupBaseEdit)
      //        {
      //            view.ShowEditor();
      //            (view.ActiveEditor as PopupBaseEdit).ShowPopup();
      //        }
      //    }));
      //}
    }

    #endregion

    #region GridLookUpEdit 模糊匹配

    /// <summary>
    /// SetGridControlAccessMethod，主要是了MyGridLookUpEdit用
    /// </summary>
    /// <param name="newControl"></param>
    protected internal virtual void SetGridControlAccessMethod(GridControl newControl) {
      SetGridControl(newControl);
    }

    /// <summary>
    /// GridLookUpEdit的模糊匹配
    /// </summary>
    /// <param name="text"></param>
    /// <param name="displayMember"></param>
    /// <returns></returns>
    protected override string OnCreateLookupDisplayFilter(string text, string displayMember) {
      List<CriteriaOperator> subStringOperators = new List<CriteriaOperator>();
      foreach (string sString in text.Split(' ')) {
        List<CriteriaOperator> columnsOperators = new List<CriteriaOperator>();
        foreach (GridColumn col in this.Columns) {
          if (col.Visible && col.ColumnType == typeof(string))
            columnsOperators.Add(new FunctionOperator(FunctionOperatorType.Contains, new OperandProperty(col.FieldName), sString));
        }
        subStringOperators.Add(new GroupOperator(GroupOperatorType.Or, columnsOperators));
      }
      return new GroupOperator(GroupOperatorType.And, subStringOperators).ToString();
    }

    /// <summary>
    /// 模糊匹配的字符串
    /// </summary>
    protected virtual internal string GetExtraFilterText => base.ExtraFilterText;

    #endregion

    /// <summary>
    /// 设置行号
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MyBandedGridView_CustomDrawRowIndicator(object sender, RowIndicatorCustomDrawEventArgs e) {
      if (e.Info.IsRowIndicator && e.RowHandle >= 0) {
        e.Info.DisplayText = (e.RowHandle + 1).ToString();
      }
    }

    /// <summary>
    /// 行号宽度随行数的变化而变化
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MyBandedGridView_RowCountChanged(object sender, EventArgs e) {
      // 根据总行数设置行号宽度
      this.IndicatorWidth = 28 + (this.RowCount.ToString().Length - 1) * 7;
    }

    /// <summary>
    /// 在查询得到0条记录时显示自定义的字符提示/显示
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MyBandedGridView_CustomDrawEmptyForeground(object sender, CustomDrawEventArgs e) {
      if (!this.EnableShowEmptyForeground) return;

      string showText = string.IsNullOrWhiteSpace(this.EmptyForegroundText) ? "没有查询到你所想要的数据!" : this.EmptyForegroundText;

      //方法一（此方法为GridView设置了数据源绑定时，可用）
      try {
        BindingSource bindingSource = this.DataSource as BindingSource;
        if (bindingSource.Count == 0) {
          string str = showText;
          Font f = new Font("宋体", 10, FontStyle.Bold);
          Rectangle r = new Rectangle(e.Bounds.Top + 5, e.Bounds.Left + 5, e.Bounds.Right - 5, e.Bounds.Height - 5);
          e.Graphics.DrawString(str, f, Brushes.Black, r);
        }
      } catch {
        //方法二（此方法为GridView没有设置数据源绑定时使用，一般使用此种方法）  
        if (this.RowCount == 0) {
          string str = showText;
          Font f = new Font("宋体", 10, FontStyle.Bold);
          Rectangle r = new Rectangle(e.Bounds.Left + 5, e.Bounds.Top + 5, e.Bounds.Width - 5, e.Bounds.Height - 5);
          e.Graphics.DrawString(str, f, Brushes.Black, r);
        }
      }
    }

    #region 单元格回车事件 add by geping@2016-12-19

    /// <summary>
    /// 默认情况下，回车或Tab按可编辑列跳转
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnDefaultKeyDown(object sender, KeyEventArgs e) {
      if (!((e.KeyCode == Keys.Enter && this.OptionsNavigation.EnterMoveNextColumn) || e.KeyCode == Keys.Tab)) return;
      if (this.ValidateEditor() == false) {
        return;
      }
      GridColumn column = null;
      var index = this.VisibleColumns.IndexOf(this.FocusedColumn);

      // 光标是否在最后一列可编辑列
      if (IsLastEditableColumn(this.FocusedColumn)) {
        #region 判断是否到达末行

        if (this.FocusedRowHandle >= this.RowCount - 1) {
          // 此处可选择跳转到首行或者直接返回或者新增行
          switch (this.ForwardType) {
            case EnumForwardType.Circle:  // 首行首列
              this.MoveFirst();
              for (int i = 0; i < this.VisibleColumns.Count; i++) {
                column = this.VisibleColumns[i];
                // 忽略不可编辑Column 
                if (!column.OptionsColumn.AllowEdit) continue;
                // 当前列可编辑，则光标定位到该列
                this.FocusedColumn = column;
                return;
              }
              break;
            case EnumForwardType.Stop:    // 停止跳转，直接返回
              e.Handled = true;
              break;
            case EnumForwardType.NewRow:  // 新增行，并跳转到新行首列
              if (this.AddNewLineEventHandler == null)
                AddNewLine();
              else
                AddNewLineEventHandler();

              this.MoveNext();
              // 没有指定定位字段
              if (string.IsNullOrWhiteSpace(this.LocatedColumn)) {
                for (int i = 0; i < this.VisibleColumns.Count; i++) {
                  column = this.VisibleColumns[i];
                  // 忽略不可编辑Column 
                  if (!column.OptionsColumn.AllowEdit) continue;
                  // 当前列可编辑，则光标定位到该列
                  this.FocusedColumn = column;
                  return;
                }
              } else {
                this.FocusedColumn = this.Columns[this.LocatedColumn];
              }
              break;
          }
          return;
        }

        #endregion

        this.MoveNext();
        for (int i = 0; i < this.VisibleColumns.Count; i++) {
          column = this.VisibleColumns[i];
          // 忽略不可编辑Column 
          if (!column.OptionsColumn.AllowEdit) continue;
          // 当前列可编辑，则光标定位到该列
          this.FocusedColumn = column;
          return;
        }
      } else {
        // 从当前定位列跳转到下一可编辑列
        for (int i = index + 1; i < this.VisibleColumns.Count; i++) {
          column = this.VisibleColumns[i];
          // 忽略不可编辑Column 
          if (!column.OptionsColumn.AllowEdit) continue;
          // 当前列可编辑，则光标定位到该列
          this.FocusedColumn = column;
          return;
        }

        // 如果光标在不可编辑列
        for (int i = 0; i <= index; i++) {
          column = this.VisibleColumns[i];
          // 忽略不可编辑Column 
          if (!column.OptionsColumn.AllowEdit) continue;
          // 当前列可编辑，则光标定位到该列
          this.FocusedColumn = column;
          return;
        }
      }
    }

    /// <summary>
    /// 自定义跳转，按指定列字段跳转
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnCustomerKeyDown(object sender, KeyEventArgs e) {
      if (!((e.KeyCode == Keys.Enter && this.OptionsNavigation.EnterMoveNextColumn) || e.KeyCode == Keys.Tab)) return;

      var fieldName = this.FocusedColumn.FieldName;

      if (this.ForwardColumnList.Contains(fieldName)) {
        var index = this.ForwardColumnList.IndexOf(fieldName);

        // 光标不在当前行指定列集合的最后一列
        if (index != this.ForwardColumnList.Count - 1) {
          this.FocusedColumn = this.Columns[this.ForwardColumnList[index + 1]];
        } else  // 光标定位当前行指定列集合的最后一列
          {
          #region 判断是否到达末行

          if (this.FocusedRowHandle >= this.RowCount - 1) {
            // 此处可选择跳转到首行或者直接返回或者新增行
            switch (this.ForwardType) {
              case EnumForwardType.Circle:  // 首行首列
                this.MoveFirst();
                this.FocusedColumn = this.Columns[this.ForwardColumnList[0]];
                break;
              case EnumForwardType.Stop:    // 停止跳转，直接返回
                e.Handled = true;
                break;
              case EnumForwardType.NewRow:  // 新增行，并跳转到新行首列
                if (this.AddNewLineEventHandler == null)
                  AddNewLine();
                else
                  AddNewLineEventHandler();

                fieldName = string.IsNullOrWhiteSpace(this.LocatedColumn) ? this.ForwardColumnList[0] : this.LocatedColumn;

                this.MoveNext();
                this.FocusedColumn = this.Columns[fieldName];
                break;
            }
            return;
          }

          #endregion

          this.MoveNext();
          this.FocusedColumn = this.Columns[this.ForwardColumnList[0]];
        }
      } else {
        this.FocusedColumn = this.Columns[this.ForwardColumnList[0]];
      }
    }

    /// <summary>
    /// 回车跳转单元格 add by geping@2016-11-25
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MyBandedGridView_KeyDown(object sender, KeyEventArgs e) {
      if (!((e.KeyCode == Keys.Enter && this.OptionsNavigation.EnterMoveNextColumn) || e.KeyCode == Keys.Tab)) return;

      // 未设置，则按默认规则跳转
      if (this.ForwardColumnList == null || this.ForwardColumnList.Count == 0)
        OnDefaultKeyDown(sender, e);
      else
        OnCustomerKeyDown(sender, e);
    }

    #endregion

    #region 重写属性

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    protected override ColumnViewOptionsView CreateOptionsView() {
      return new CustomBandedGridOptionsView();
    }

    ///// <summary>
    ///// 
    ///// </summary>
    ///// <returns></returns>
    //protected override ColumnViewOptionsFilter CreateOptionsFilter() {
    //  return new CustomGridOptionsFilter();
    //}

    ///// <summary>
    ///// 
    ///// </summary>
    ///// <returns></returns>
    //protected override ColumnViewOptionsSelection CreateOptionsSelection() {
    //  return new CustomGridOptionsSelection();
    //}

    ///// <summary>
    ///// 
    ///// </summary>
    ///// <returns></returns>
    //protected override GridOptionsDetail CreateOptionsDetail() {
    //  return new CustomGridOptionsDetail();
    //}

    ///// <summary>
    ///// 
    ///// </summary>
    ///// <returns></returns>
    //protected override ColumnViewOptionsBehavior CreateOptionsBehavior() {
    //  return new CustomGridOptionsBehavior();
    //}

    ///// <summary>
    ///// 
    ///// </summary>
    ///// <returns></returns>
    //protected override ViewPrintOptionsBase CreateOptionsPrint() {
    //  return new CustomBandedGridOptionsPrint();
    //}

    ///// <summary>
    ///// 
    ///// </summary>
    ///// <returns></returns>
    //protected override GridOptionsNavigation CreateOptionsNavigation() {
    //  return new CustomGridOptionsNavigation();
    //}

    ///// <summary>
    ///// 
    ///// </summary>
    ///// <returns></returns>
    //protected override GridOptionsCustomization CreateOptionsCustomization() {
    //  return new CustomBandedGridOptionsCustomization();
    //}

    #endregion
  }

  /// <summary>
  /// 
  /// </summary>
  public class MyBandedGridInfoRegistrator : BandedGridInfoRegistrator {
    /// <summary>
    /// MyBandedGridInfoRegistrator
    /// </summary>
    public override string ViewName => "MyBandedGridView";

    /// <summary>
    /// Create BaseView
    /// </summary>
    /// <param name="grid"></param>
    /// <returns></returns>
    public override BaseView CreateView(GridControl grid) {
      return new MyBandedGridView(grid as GridControl);
    }

    /// <summary>
    /// Create BaseViewInfo
    /// </summary>
    /// <param name="view"></param>
    /// <returns></returns>
    public override BaseViewInfo CreateViewInfo(BaseView view) {
      return new MyBandedGridViewInfo(view as MyBandedGridView);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="view"></param>
    /// <returns></returns>
    public override BaseViewHandler CreateHandler(BaseView view) {
      return new MyBandedGridHandler(view as MyBandedGridView);
    }
  }

  /// <summary>
  /// Create a new MyBandedGridViewInfo object
  /// </summary>
  public class MyBandedGridViewInfo : BandedGridViewInfo {
    /// <summary>
    /// Create a new MyBandedGridViewInfo object
    /// </summary>
    /// <param name="gridView">BandedGridView</param>
    public MyBandedGridViewInfo(BandedGridView gridView)
      : base(gridView) {
    }
  }

  /// <summary>
  /// BandedGridHandler
  /// </summary>
  public class MyBandedGridHandler : BandedGridHandler {
    /// <summary>
    /// Create BandedGridHandler
    /// </summary>
    /// <param name="gridView"></param>
    public MyBandedGridHandler(BandedGridView gridView) : base(gridView) {
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyDown(KeyEventArgs e) {
      base.OnKeyDown(e);

      // Ctrl + C 复制单元格
      if (e.Control & e.KeyCode == Keys.C) {
        Clipboard.SetDataObject(this.View.GetFocusedRowCellDisplayText(this.View.FocusedColumn));
        e.Handled = true;
      }
    }

  }
}
